﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.CodeDom;
using System.ComponentModel.Composition;

namespace NeuroSpeech.XamlExtensions
{
    [Export]
    public class ColorConverter : DefaultConverter
    {

        #region public override bool  CanProcess(XamlCodeContext context)
        public override bool CanProcess(XamlCodeContext context)
        {
            Type type = context.Peek.MemberType;
            if (type != null && type.FullName == "System.Windows.Media.Color")
                return true;
            return base.CanProcess(context);
        }
        #endregion

        #region protected override CodeExpression  ConvertValue(Type type, object val)
        protected override CodeExpression ConvertValue(Type type, object val)
        {

            string strValue = val.ToString();

            Type colorType = typeof(Colors);
            if (colorType.GetProperty(strValue) != null)
            {
                return new CodePropertyReferenceExpression
                {
                    TargetObject = new CodeTypeReferenceExpression("System.Windows.Media.Colors"),
                    PropertyName = strValue
                };
            }

            Color c = ParseColor(strValue);
            CodeMethodInvokeExpression cc = new CodeMethodInvokeExpression
            {
                Method = new CodeMethodReferenceExpression
                {
                    TargetObject = new CodeTypeReferenceExpression("System.Windows.Media.Color"),
                    MethodName = "FromArgb"
                }
            };
            cc.Parameters.Add(new CodePrimitiveExpression(c.A));
            cc.Parameters.Add(new CodePrimitiveExpression(c.R));
            cc.Parameters.Add(new CodePrimitiveExpression(c.G));
            cc.Parameters.Add(new CodePrimitiveExpression(c.B));
            return cc;
        }

        #region private Color ParseColor(string p)
        private Color ParseColor(string str)
        {

            str = str.Trim();

            bool isNumericColor = false;
            bool isContextColor = false;

            if ((((str.Length == 4) || (str.Length == 5)) || ((str.Length == 7) || (str.Length == 9))) && (str[0] == '#'))
            {
                isNumericColor = true;
            }
            if (str.StartsWith("ContextColor ", StringComparison.OrdinalIgnoreCase))
            {
                isContextColor = true;
            }

            if(isNumericColor)
                return ParseHexColor(str);
            if (isContextColor)
                return ParseContextColor(str);
            return ParseScRgbColor(str);
        }

        #region private Color ParseScRgbColor(string trimmedColor)
        private Color ParseHexColor(string trimmedColor)
        {
            int num;
            int num2;
            int num3;
            int num4 = 0xff;
            if (trimmedColor.Length > 7)
            {
                num4 = (ParseHexChar(trimmedColor[1]) * 0x10) + ParseHexChar(trimmedColor[2]);
                num3 = (ParseHexChar(trimmedColor[3]) * 0x10) + ParseHexChar(trimmedColor[4]);
                num2 = (ParseHexChar(trimmedColor[5]) * 0x10) + ParseHexChar(trimmedColor[6]);
                num = (ParseHexChar(trimmedColor[7]) * 0x10) + ParseHexChar(trimmedColor[8]);
            }
            else if (trimmedColor.Length > 5)
            {
                num3 = (ParseHexChar(trimmedColor[1]) * 0x10) + ParseHexChar(trimmedColor[2]);
                num2 = (ParseHexChar(trimmedColor[3]) * 0x10) + ParseHexChar(trimmedColor[4]);
                num = (ParseHexChar(trimmedColor[5]) * 0x10) + ParseHexChar(trimmedColor[6]);
            }
            else if (trimmedColor.Length > 4)
            {
                num4 = ParseHexChar(trimmedColor[1]);
                num4 += num4 * 0x10;
                num3 = ParseHexChar(trimmedColor[2]);
                num3 += num3 * 0x10;
                num2 = ParseHexChar(trimmedColor[3]);
                num2 += num2 * 0x10;
                num = ParseHexChar(trimmedColor[4]);
                num += num * 0x10;
            }
            else
            {
                num3 = ParseHexChar(trimmedColor[1]);
                num3 += num3 * 0x10;
                num2 = ParseHexChar(trimmedColor[2]);
                num2 += num2 * 0x10;
                num = ParseHexChar(trimmedColor[3]);
                num += num * 0x10;
            }
            return Color.FromArgb((byte)num4, (byte)num3, (byte)num2, (byte)num);
        }

        #region private int ParseHexChar(char p)
        private int ParseHexChar(char c)
        {
            int num = c;
            if ((num >= 0x30) && (num <= 0x39))
            {
                return (num - 0x30);
            }
            if ((num >= 0x61) && (num <= 0x66))
            {
                return ((num - 0x61) + 10);
            }
            if ((num < 0x41) || (num > 70))
            {
                throw new FormatException("Illegal Color Code");
            }
            return ((num - 0x41) + 10);
        }
        #endregion

        #endregion


        #region private Color ParseContextColor(string str)
        private Color ParseContextColor(string str)
        {
            throw new NotImplementedException();
        }
        #endregion


        #region private Color ParseHexColor(string str)
        private Color ParseScRgbColor(string str)
        {
            throw new NotImplementedException();
        }
        #endregion

        #endregion

        #endregion

    }
}
